#include "fractalmarkerset.h"
#include <iostream>
#include <fstream>

namespace aruco
{

FractalMarkerSet FractalMarkerSet::load(std::string info){
    if (isPredefinedConfigurationString(info))
        return loadPredefined(info);
    else return readFromFile(info);
}

FractalMarkerSet FractalMarkerSet::loadPredefined(std::string type){
    return loadPredefined(getTypeFromString(type));
}

FractalMarkerSet FractalMarkerSet::loadPredefined(CONF_TYPES type){
    FractalMarkerSet fms;

    switch(type){
        case FRACTAL_2L_6:{
            unsigned char _conf_2L_6[] = {
                0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
                0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,
                0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x24, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0xbe, 0xab, 0xaa, 0xaa, 0x3e,
                0x00, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0x3e, 0xab, 0xaa, 0xaa, 0x3e,
                0x00, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0x3e, 0xab, 0xaa, 0xaa, 0xbe,
                0x00, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0xbe, 0xab, 0xaa, 0xaa, 0xbe,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
                0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
                0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
            };
            unsigned int _conf_2L_6_len = 272;

            std::stringstream stream;
            stream.write((char*) _conf_2L_6, sizeof(unsigned char)*_conf_2L_6_len);
            _fromStream(fms, stream);
        }break;
        case FRACTAL_3L_6:{
            unsigned char _conf_3L_6[] = {
                0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
                0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
                0xb7, 0x6d, 0xdb, 0xbe, 0xb7, 0x6d, 0xdb, 0x3e, 0x00, 0x00, 0x00, 0x00,
                0xb7, 0x6d, 0xdb, 0x3e, 0xb7, 0x6d, 0xdb, 0x3e, 0x00, 0x00, 0x00, 0x00,
                0xb7, 0x6d, 0xdb, 0x3e, 0xb7, 0x6d, 0xdb, 0xbe, 0x00, 0x00, 0x00, 0x00,
                0xb7, 0x6d, 0xdb, 0xbe, 0xb7, 0x6d, 0xdb, 0xbe, 0x00, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
                0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
                0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
                0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x49, 0x12, 0xbe,
                0x25, 0x49, 0x12, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x25, 0x49, 0x12, 0x3e,
                0x25, 0x49, 0x12, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x25, 0x49, 0x12, 0x3e,
                0x25, 0x49, 0x12, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x25, 0x49, 0x12, 0xbe,
                0x25, 0x49, 0x12, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
                0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            };
            unsigned int _conf_3L_6_len = 480;

            std::stringstream stream;
            stream.write((char*) _conf_3L_6, sizeof(unsigned char)*_conf_3L_6_len);
            _fromStream(fms, stream);
        }break;
        case FRACTAL_4L_6:{
            unsigned char _conf_4L_6[] = {
                0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
                0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00,
                0x00, 0xef, 0xee, 0xee, 0xbe, 0xef, 0xee, 0xee, 0x3e, 0x00, 0x00, 0x00,
                0x00, 0xef, 0xee, 0xee, 0x3e, 0xef, 0xee, 0xee, 0x3e, 0x00, 0x00, 0x00,
                0x00, 0xef, 0xee, 0xee, 0x3e, 0xef, 0xee, 0xee, 0xbe, 0x00, 0x00, 0x00,
                0x00, 0xef, 0xee, 0xee, 0xbe, 0xef, 0xee, 0xee, 0xbe, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01,
                0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
                0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
                0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
                0x00, 0x64, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0xbe, 0xcd, 0xcc, 0x4c,
                0x3e, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0x3e, 0xcd, 0xcc, 0x4c,
                0x3e, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0x3e, 0xcd, 0xcc, 0x4c,
                0xbe, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0xbe, 0xcd, 0xcc, 0x4c,
                0xbe, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01,
                0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
                0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00,
                0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
                0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
                0x00, 0x89, 0x88, 0x88, 0xbd, 0x89, 0x88, 0x88, 0x3d, 0x00, 0x00, 0x00,
                0x00, 0x89, 0x88, 0x88, 0x3d, 0x89, 0x88, 0x88, 0x3d, 0x00, 0x00, 0x00,
                0x00, 0x89, 0x88, 0x88, 0x3d, 0x89, 0x88, 0x88, 0xbd, 0x00, 0x00, 0x00,
                0x00, 0x89, 0x88, 0x88, 0xbd, 0x89, 0x88, 0x88, 0xbd, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01,
                0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00
            };
            unsigned int _conf_4L_6_len = 713;

            std::stringstream stream;
            stream.write((char*) _conf_4L_6, sizeof(unsigned char)*_conf_4L_6_len);
            _fromStream(fms, stream);
        }break;
        case FRACTAL_5L_6:{
            unsigned char _conf_5L_6[] = {
                0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf,
                0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00,
                0x00, 0x4f, 0xec, 0xc4, 0xbe, 0x4f, 0xec, 0xc4, 0x3e, 0x00, 0x00, 0x00,
                0x00, 0x4f, 0xec, 0xc4, 0x3e, 0x4f, 0xec, 0xc4, 0x3e, 0x00, 0x00, 0x00,
                0x00, 0x4f, 0xec, 0xc4, 0x3e, 0x4f, 0xec, 0xc4, 0xbe, 0x00, 0x00, 0x00,
                0x00, 0x4f, 0xec, 0xc4, 0xbe, 0x4f, 0xec, 0xc4, 0xbe, 0x00, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
                0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
                0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
                0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
                0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
                0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x7d, 0xcb, 0x37, 0xbe, 0x7d, 0xcb,
                0x37, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xcb, 0x37, 0x3e, 0x7d, 0xcb,
                0x37, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xcb, 0x37, 0x3e, 0x7d, 0xcb,
                0x37, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xcb, 0x37, 0xbe, 0x7d, 0xcb,
                0x37, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
                0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00,
                0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xd9, 0x89,
                0x9d, 0xbd, 0xd9, 0x89, 0x9d, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x89,
                0x9d, 0x3d, 0xd9, 0x89, 0x9d, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x89,
                0x9d, 0x3d, 0xd9, 0x89, 0x9d, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x89,
                0x9d, 0xbd, 0xd9, 0x89, 0x9d, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
                0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
                0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01,
                0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
                0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,
                0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x21, 0x0d, 0xd2, 0xbc, 0x21, 0x0d,
                0xd2, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x21, 0x0d, 0xd2, 0x3c, 0x21, 0x0d,
                0xd2, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x21, 0x0d, 0xd2, 0x3c, 0x21, 0x0d,
                0xd2, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x21, 0x0d, 0xd2, 0xbc, 0x21, 0x0d,
                0xd2, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
                0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01,
                0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            };
            unsigned int _conf_5L_6_len = 898;

            std::stringstream stream;
            stream.write((char*) _conf_5L_6, sizeof(unsigned char)*_conf_5L_6_len);
            _fromStream(fms, stream);
        }break;
        case CUSTOM:
            throw cv::Exception(-1,"CUSTOM type is only set by loading from file","FractalMarkerSet::loadPredefined","fractalmarkerset.h",-1);
        break;

        default:           throw cv::Exception(9001, "Invalid Dictionary type requested", "Dictionary::loadPredefined", __FILE__, __LINE__);

    }
    return fms;
}

bool FractalMarkerSet::isPredefinedConfigurationString(std::string str)  {
       return getTypeFromString(str)!=CUSTOM;
}

std::string FractalMarkerSet::getTypeString(CONF_TYPES t)  {
        switch(t){
            case FRACTAL_2L_6:return "FRACTAL_2L_6";
            case FRACTAL_3L_6:return "FRACTAL_3L_6";
            case FRACTAL_4L_6:return "FRACTAL_4L_6";
            case FRACTAL_5L_6:return "FRACTAL_5L_6";
            case CUSTOM:return "CUSTOM";
        };
       return "Non valid CONF_TYPE";
    }

FractalMarkerSet::CONF_TYPES FractalMarkerSet::getTypeFromString(std::string str)  {
        if (str=="FRACTAL_2L_6") return FRACTAL_2L_6;
        if (str=="FRACTAL_3L_6") return FRACTAL_3L_6;
        if (str=="FRACTAL_4L_6") return FRACTAL_4L_6;
        if (str=="FRACTAL_5L_6") return FRACTAL_5L_6;
        else  return CUSTOM;
    }

std::vector<std::string> FractalMarkerSet::getConfigurations() {
    return {"FRACTAL_2L_6","FRACTAL_3L_6","FRACTAL_4L_6","FRACTAL_5L_6"};
}

void FractalMarkerSet::_toStream(FractalMarkerSet &configuration, std::ostream &str)
{
    str.write((char*)&configuration.mInfoType,sizeof(mInfoType));
    str.write((char*)&configuration._nmarkers,sizeof(_nmarkers));
    str.write((char*)&configuration._idExternal,sizeof(_idExternal));

    for(auto fractal:configuration.fractalMarkerCollection)
    {
        //ID
        int id = fractal.first;
        str.write((char*)&id,sizeof(id));
        //NBITS
        int nbits = fractal.second.nBits();
        str.write((char*)&nbits,sizeof(nbits));
        //CORNERS
        std::vector<cv::Point3f> corners = fractal.second.points;
        str.write((char*)&corners[0],sizeof(cv::Point3f)*4);
        //MAT
        cv::Mat mat = fractal.second.mat();
        str.write((char*)mat.data, mat.elemSize() * mat.total());
        //SUBMARKERS
        std::vector<int> sub = fractal.second.subMarkers();
        int nsub = sub.size();
        str.write((char*)&nsub,sizeof(nsub));
        str.write((char*)&sub[0],sizeof(int)*nsub);
    }
}

void FractalMarkerSet::_fromStream(FractalMarkerSet &configuration, std::istream &str)
{
    str.read((char*)&configuration.mInfoType,sizeof(mInfoType));
    str.read((char*)&configuration._nmarkers,sizeof(_nmarkers));
    str.read((char*)&configuration._idExternal,sizeof(_idExternal));

    for(int i=0; i<configuration._nmarkers; i++)
    {
        //ID
        int id;
        str.read((char*)&id,sizeof(id));
        //NBITS
        int nbits;
        str.read((char*)&nbits,sizeof(nbits));

        //CORNERS
        std::vector<cv::Point3f> corners(4);
        str.read((char*)&corners[0],sizeof(cv::Point3f)*4);
        //MAT
        cv::Mat mat;
        mat.create(sqrt(nbits), sqrt(nbits), CV_8UC1);
        str.read((char*)mat.data, mat.elemSize() * mat.total());
        //SUBMARKERS
        int nsub;
        str.read((char*)&nsub,sizeof(nsub));
        std::vector<int> id_submarkers(nsub);
        if (nsub > 0)
            str.read((char*)&id_submarkers[0],sizeof(int)*nsub);

        FractalMarker fractalMarker = FractalMarker(id, mat, corners, id_submarkers);
        configuration.nbits_fractalMarkerIDs[mat.total()].push_back(fractalMarker.id);
        configuration.fractalMarkerCollection[fractalMarker.id] = fractalMarker;
    }

    //Add subfractals
    for(auto &id_marker:configuration.fractalMarkerCollection)
    {
        FractalMarker &marker = id_marker.second;
        for(auto id:id_marker.second.subMarkers())
            marker.addSubFractalMarker(configuration.fractalMarkerCollection[id]);
    }
}

void FractalMarkerSet::create(std::vector<std::pair<int,int>> regionsConfig, float pixSize)
{
    if(pixSize == -1)
    {
        mInfoType = NORM;
        pixSize = 1;
    }
    else
        mInfoType = PIX;

    _nmarkers = regionsConfig.size();
    _idExternal = 0;

    std::vector<int> submarkers;
    submarkers.clear();
    float pix = 0;
    for(int n=regionsConfig.size()-1; n>=0; n--)
    {
        int nVal = regionsConfig[n].first;
        int kVal = regionsConfig[n].second;

        cv::Mat mat = configureMat(nVal, kVal);

        pix = (nVal + 2) * pixSize;
        std::vector<cv::Point3f> corners = { cv::Point3f(-pix/2, pix/2, 0.),
                                             cv::Point3f(pix/2, pix/2, 0.),
                                             cv::Point3f(pix/2, -pix/2, 0.),
                                             cv::Point3f(-pix/2, -pix/2, 0.)
                                           };

        FractalMarker fractal = FractalMarker(n, mat, corners, submarkers);
        fractalMarkerCollection[n] = fractal;
        submarkers.clear();
        submarkers.push_back(n);


        float kValSup = regionsConfig[n-1].second - 2;
        float newP = (nVal+2)/(kValSup);
        pixSize = newP * pixSize;
    }

    //Normalize corners. Fractal marker: (-1,1,0)(1,1,0)(1,-1,0)(-1,-1,0)
    if(isNormalize()){
        for(auto &m:fractalMarkerCollection){
            for(auto &c:m.second.points)
            {
                c.x/=pix/2;
                c.y/=pix/2;
            }
        }
    }
}

cv::Mat FractalMarkerSet::configureMat(int nVal, int kVal, int maxIter)
{
    //Pixels to configure (n-k region)
    std::vector<cv::Point2i> pixels;
    for(int y=0; y<nVal; y++) {
        for(int x=0; x<nVal; x++) {
            if((x <= ((nVal-kVal)/2)-1 || x >= kVal+(nVal-kVal)/2)
                    || (y <= ((nVal-kVal)/2)-1 || y >= kVal+(nVal-kVal)/2)){
                pixels.push_back(cv::Point2i(x, y));
            }
        }
    }

    int dst_mkr = 0;
    int dst_set=0;

    cv::Mat m;
    int markerIters = 0;
    do{
        std::vector<cv::Point2i> conf_pixels = pixels;
        m = cv::Mat::ones(nVal, nVal, CV_8UC1);

//        struct timespec ts;
//        clock_gettime(CLOCK_MONOTONIC, &ts);
//        srand((time_t)ts.tv_nsec);

        //Random delete half of pixels
        int npix = conf_pixels.size()/2;
        for(int i=0; i<npix; i++) {
            int idxSelected = rand() % conf_pixels.size();
            conf_pixels.erase(conf_pixels.begin() + idxSelected);
        }

        //Put the new configuration (0 selected pixels)
        for(auto p:conf_pixels)
            m.at<char>(p.y,p.x) = 0;

        //Check marker distance to itself
        int new_dst_mkr = dstMarker(m);
        if(new_dst_mkr > dst_mkr)
        {
            //Check marker distance to set
            int new_dst_set = dstMarkerToFractalDict(m);
            if(new_dst_set > dst_set)
            {
                dst_mkr = new_dst_mkr;
                dst_set = new_dst_set;
            }
        }
    } while(markerIters++<maxIter);

    for(int y=((nVal-kVal)/2)+1; y<kVal+(nVal-kVal)/2-1; y++) {
        for(int x=((nVal-kVal)/2)+1; x<kVal+(nVal-kVal)/2-1; x++) {
                m.at<char>(y,x)=0;
            }
        }

    return m;
}

/*
 *  Calculate minimum distance between marker 'm' and the 4 rotations of each word in the dictionary
 */
int FractalMarkerSet::dstMarkerToFractalDict(cv::Mat m){
    int HDist = m.cols * m.rows; //distancia maxima
    int HDistTemp;

    for(auto marker:fractalMarkerCollection) {
        if(marker.second.nBits() == m.total())
        {
            HDistTemp = dstMarkerToMarker(marker.second.mat(), m);

            if(HDistTemp == 0)
                return 0;
            else if(HDistTemp < HDist)
                HDist = HDistTemp;
        }
    }
    return HDist;
}

/*
 *  Calculate minimum distance between marker1 'm' and the 4 rotations of marker2 'm2'
 */
auto rotate=[](const cv::Mat &m) {
    cv::Mat out;
    m.copyTo(out);
    for (int i = 0; i < m.rows; i++) {
        for (int j = 0; j < m.cols; j++) {
            out.at< char >(i, j) = m.at< char >(m.cols - j - 1, i);
        }
    }
    return out;
};

int FractalMarkerSet::dstMarker(const cv::Mat m) {

    int HDist = m.cols * m.rows;//maximum distance
    int HDistTemp;

    cv::Mat rot;
    m.copyTo(rot);


    for(int i=0; i<3; i++)
    {
        cv::Mat diff;
        rot=rotate(rot);
        cv::compare(rot, m, diff, cv::CMP_NE);
        HDistTemp = cv::countNonZero(diff);
        if(HDistTemp < HDist)
            HDist = HDistTemp;
    }
    return HDist;
}

int FractalMarkerSet::dstMarkerToMarker(const cv::Mat m1, const cv::Mat m2) {

    int HDist = m2.cols * m2.rows;//maximum distance
    int HDistTemp;

    for(int i=0; i<4; i++)
    {
        cv::Mat diff;
        cv::compare(rotate(m2), m1, diff, cv::CMP_NE);
        HDistTemp = cv::countNonZero(diff);
        if(HDistTemp < HDist)
            HDist = HDistTemp;
    }

    return HDist;
}


FractalMarkerSet FractalMarkerSet::readFromFile(std::string path)
{
    cv::FileStorage fs;
    try
    {
        fs.open(path, cv::FileStorage::READ);
    }
    catch (std::exception& ex)
    {
        throw cv::Exception(81818, "FractalMarkerSet::readFromFile", ex.what() + std::string(" file=)") + path, __FILE__, __LINE__);
    }

    FractalMarkerSet configuration;

    fs["mInfoType"] >> configuration.mInfoType;
    fs["fractal_levels"] >> configuration._nmarkers;
    fs["fractal_external_id"] >> configuration._idExternal;

    cv::FileNode markers = fs["markers"];
    int i = 0;
    for (cv::FileNodeIterator it = markers.begin(); it != markers.end(); ++it, i++)
    {
        int id = (*it)["id"];
        std::vector<int> bits;

        std::vector<cv::Point3f> corners;
        std::vector<int> submarkers_id;

        cv::FileNode bitsMarker = (*it)["bits"];
        for (cv::FileNodeIterator itb = bitsMarker.begin(); itb != bitsMarker.end(); ++itb)
        {
            bits.push_back(*itb);
        }
        cv::Mat m = cv::Mat(sqrt(bits.size()), sqrt(bits.size()), CV_32SC1);
        memcpy(m.data, bits.data(), bits.size()*sizeof(int));

        m.convertTo(m,CV_8UC1);

        cv::FileNode cornersFractal = (*it)["corners"];
        for (cv::FileNodeIterator itp = cornersFractal.begin(); itp != cornersFractal.end(); ++itp)
        {
            std::vector<float> coordinates3d;
            (*itp) >> coordinates3d;
            if (coordinates3d.size() != 3)
                throw cv::Exception(81818, "FractalMarkerSet::readFromFile", "invalid file type 3", __FILE__, __LINE__);
            cv::Point3f point(coordinates3d[0], coordinates3d[1], coordinates3d[2]);
            corners.push_back(point);
        }

        cv::FileNode submarkersID = (*it)["submarkers_id"];
        for (cv::FileNodeIterator itm = submarkersID.begin(); itm != submarkersID.end(); ++itm)
        {
            submarkers_id.push_back((*itm));
        }

        FractalMarker fractalMarker = FractalMarker(id, m, corners, submarkers_id);
        configuration.nbits_fractalMarkerIDs[m.total()].push_back(fractalMarker.id);
        configuration.fractalMarkerCollection[fractalMarker.id] = fractalMarker;
    }

    //Add subfractals
    for(auto &id_marker:configuration.fractalMarkerCollection)
    {
        FractalMarker &marker = id_marker.second;
        for(auto id:id_marker.second.subMarkers())
            marker.addSubFractalMarker(configuration.fractalMarkerCollection[id]);
    }

    return configuration;
}

    void FractalMarkerSet::saveToFile(cv::FileStorage& fs)
    {
        fs << "codeid" << "fractalmarkers";
        fs << "mInfoType" << mInfoType;
        fs << "fractal_levels" << _nmarkers;
        fs << "fractal_external_id" << _idExternal;
        fs << "markers"
           << "[";
        for(auto id_marker:fractalMarkerCollection) {

            FractalMarker marker = id_marker.second;

            fs << "{:"
               << "id" << (int)id_marker.first;

            fs << "bits"
                << "[:";
                cv::Mat m = marker.mat();
                for (int y = 0; y < m.cols; y++)
                    for (int x = 0; x < m.rows; x++)
                        if (m.at<char>(y, x) == 2)
                            fs << 0;
                        else
                            fs << m.at<char>(y, x);
            fs << "]";

            fs << "corners"
               << "[:";
                for (auto corner:marker.points)
                    fs << corner;
            fs << "]";

            fs << "submarkers_id"
               << "[:";
                for (auto idsub:marker.subMarkers())
                    fs << (int) idsub;
            fs << "]";

            fs << "}";
        }
        fs << "]";
    }

    bool FractalMarkerSet::isFractalMarker(cv::Mat &m, int nbits, int& markerid)
    {

        bool found = false;

        for(auto id:nbits_fractalMarkerIDs[nbits]){
            FractalMarker fm = fractalMarkerCollection[id];

            //Apply mask to substract submarkers
            cv::Mat m2;
            m.copyTo(m2, fm.mask());

            //Code without submarkers == fractal marker?
            if (cv::countNonZero(m2 != fm.mat()) == 0){
                found = true;

                //Change new code!!
                //////////////
                markerid = fm.id;
                /////////////

                break;
            }
        }

        return found;
    }

    FractalMarkerSet FractalMarkerSet::convertToMeters(float fractalSizeM)
    {
        if (!(isExpressedInPixels() || isNormalize()))
            throw cv::Exception(-1, "The FractalMarkers are not expressed in pixels", "FractalMarkerSet::convertToMeters", __FILE__,
                                __LINE__);

        FractalMarkerSet BInfo(*this);
        BInfo.mInfoType = FractalMarkerSet::METERS;

        // now, get the size of a pixel, and change scale
        float pixSizeM = fractalSizeM / float(BInfo.getFractalSize());

        for (size_t i=0; i < BInfo.fractalMarkerCollection.size(); i++)
        {
            //Convert to meters the position fractal marker
            for (int c = 0; c < 4; c++)
            {
                BInfo.fractalMarkerCollection[i][c] *= pixSizeM;
            }
        }
        return BInfo;
    }

    FractalMarkerSet FractalMarkerSet::normalize()
    {
        if (!(isExpressedInPixels() || isExpressedInMeters()))
            throw cv::Exception(-1, "The FractalMarkers are not expressed in pixels or meters", "FractalMarkerSet::convertToMeters", __FILE__,
                                __LINE__);

        FractalMarkerSet BInfo(*this);
        BInfo.mInfoType = FractalMarkerSet::NORM;

        float currentHalfSize = BInfo.getFractalSize()/2.f;

        for (size_t i=0; i < BInfo.fractalMarkerCollection.size(); i++)
        {
            //Normalize the position fractal marker
            for (size_t c = 0; c < 4; c++)
            {
                BInfo.fractalMarkerCollection[i][c] /= currentHalfSize;
            }
        }

        return BInfo;
    }

    std::map<int, std::vector<cv::Point3f>> FractalMarkerSet::getInnerCorners()
    {
        std::map<int, std::vector<cv::Point3f>> id_innerCorners;

        for(auto id_fm:fractalMarkerCollection)
        {
            int id = id_fm.first;
            FractalMarker fm = id_fm.second;

            for(auto ic:fm.getInnerCorners())
                id_innerCorners[id].push_back(ic); //Conversion

        }
        return id_innerCorners;
    }

    cv::Mat FractalMarkerSet::getFractalMarkerImage(int pixSize, bool border)
    {
        if(fractalMarkerCollection.size()<1)
            throw cv::Exception(9001, "There is not any fractal marker loaded",
                                "FractalMarkerSet::getFractalMarkerImage", __FILE__, __LINE__);

        //Smallest fractal marker
        FractalMarker innerM = (--fractalMarkerCollection.end())->second;
        float bitSize = innerM.getMarkerSize() / (pixSize * (sqrt(innerM.nBits())+2));

        FractalMarker externMarker = fractalMarkerCollection[_idExternal];
        float markerSize = externMarker.getMarkerSize()/bitSize;
        float markerBitSize = markerSize/(sqrt(externMarker.nBits())+2);
        cv::Mat img=cv::Mat::zeros(markerSize, markerSize, CV_8U);

        //Asign value pixels
        cv::Mat m = externMarker.mat();

        for (int y = m.cols-1; y >=0 ; y--)
            for (int x = m.cols-1; x >=0; x--){
                if (m.at<uchar>(y,x) == 1){
                    cv::Range val1 = cv::Range((1+y)*markerBitSize,(y+2)*markerBitSize);
                    cv::Range val2 = cv::Range((1+x)*markerBitSize,(x+2)*markerBitSize);

                    cv::Mat bit_pix=img(val1, val2);
                    bit_pix.setTo(cv::Scalar::all(255));
                }
            }

        for(auto idSubmarker:externMarker.subMarkers()){
            std::vector<int> idds;
            idds.push_back(idSubmarker);
            while(!idds.empty())
            {
                idSubmarker = idds.back();
                idds.pop_back();

                FractalMarker submarker = fractalMarkerCollection[idSubmarker];

                cv::Mat m = submarker.mat();
                cv::Point3f coord = submarker.points[0];

                float markerSize = submarker.getMarkerSize()/bitSize;
                float markerBitSize = markerSize/(sqrt(submarker.nBits())+2);

                //Get position inside fractal marker
                float offsetX = fabs(coord.x - externMarker.points[0].x)/bitSize ;
                float offsetY = fabs(coord.y - externMarker.points[0].y)/bitSize;

                //Asign value pixels
                for (int y = m.cols-1; y >=0 ; y--)
                    for (int x = m.cols-1; x >=0; x--){
                        if (m.at<uchar>(y,x) == 1){
                            cv::Range val1 = cv::Range((1+y)*markerBitSize + offsetY,(2+y)*markerBitSize + offsetY);
                            cv::Range val2 = cv::Range((1+x)*markerBitSize + offsetX,(2+x)*markerBitSize + offsetX);

                            cv::Mat bit_pix=img(val1, val2);
                            bit_pix.setTo(cv::Scalar::all(255));
                        }
                    }

                //Add submarkers to draw
                for(auto idsm:submarker.subMarkers())
                    idds.push_back(idsm);
            }
        }

        if(border)
            copyMakeBorder(img,img,markerBitSize,markerBitSize,markerBitSize,markerBitSize,cv::BORDER_CONSTANT,cv::Scalar::all(255));

        return img;
    }
};

